#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>
#include<signal.h>
#include<functional>
#include"log.hpp"
#include"Protocol.hpp"

using namespace std;

namespace server
{enum
    {
        USAGE_ERR = 1,
        SOCKET_ERR,
        BIND_ERR,
        LISTEN_ERR
    };
    //构建函数的指针
  typedef function<void(request&,response*)> func_t ;
  void Handler(int sock,func_t func)
 { static string inbuffer;
  while(true)
    {
    //1.获取完整的字符串请求

    string message;
    if(!recvmessage(sock,&message,&inbuffer)) return;;
    string revm;
    if(!delength(message,&revm) ) return ;//去报头

    //2.对请求进行反序列化
    request req;
    req.deserialize(revm);
    response resp;
    func(req,&resp);
    
    string sendmessage;
    resp.serialize(&sendmessage);
     std::cout << "计算完成, 序列化响应: " <<  sendmessage << std::endl;
    string sendm=enlength(sendmessage);
     std::cout << "构建完成完整的响应\n" <<  sendm << std::endl;
    send(sock,sendm.c_str(),sendm.size(),0);
     }
  


  }

  static const uint16_t gport=8080;
  static const int gbacklog=5;
  //static const std::string ip="0.0.0.0";
  class Calserver
  { public:
     Calserver(const uint16_t &port=gport):_listensock(-1),_port(port)
{}
    void initServer()
    {   //1.创建套接字
        _listensock=socket(AF_INET,SOCK_STREAM,0);
        if(_listensock<0)
        {
            logMessage(FATAL, "create socket error");
                exit(SOCKET_ERR);
        }
        logMessage(NORMAL,"create socket success");
        int opt=1;
        setsockopt(_listensock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
        //2.绑定服务端的网络信息到结构体上
           struct sockaddr_in local;
            memset(&local, 0, sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            local.sin_addr.s_addr = INADDR_ANY;//任意ip
            if (bind(_listensock, (struct sockaddr *)&local, sizeof(local)) < 0)
            {
                logMessage(FATAL, "bind socket error");
                exit(BIND_ERR);
            }
            logMessage(NORMAL, "bind socket success");
            //3.设置套接字为监听状态
            if(listen(_listensock,gbacklog)<0)
            {
                logMessage(FATAL, "listen socket error");
                exit(LISTEN_ERR);
            }
            logMessage(NORMAL,"listensocket success");
    }
    void start(func_t func)
    { 
      for(;;)
      {
        //4.获取链接
        struct sockaddr_in peer;
        socklen_t len=sizeof(peer);
        //建立链接是在accept之前，客户端os发出链接请求，服务端os接受
        int sock =accept(_listensock,(struct sockaddr*)&peer,&len);//sock为得到客户端传递信息的文件描述符
        if(sock<0)
        {
            logMessage(ERROR, "accept error, next");
                    continue;

        }
        logMessage(NORMAL, "accept success 文件描述符：%d", sock);
    
          int n =fork();
          if(n==0)
          {close(_listensock);
          Handler(sock,func);
          close(sock);
          exit(0);
          }
          close(sock);
        

       }
      
    }
   
  
   ~Calserver()
    {
        if (_listensock != -1)
        {
            close(_listensock);  // 关闭监听套接字
            _listensock = -1;
        }
    }

   

    private:
    int _listensock;
    uint16_t _port;
  };




}
